// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package types2

// 一个术语描述基本类型集：
// 
// ∅:  （*期限）（无）=∅                      
// 𝓤:  &术语{}==𝓤                      
// T:&term{false，T}=={T}
// ~T:&term{true，T}==={T'|在（T'）==T}
// 
type term struct {
	tilde bool // 如果类型为typ！=nil 
	typ   Type
}

func (x *term) String() string {
	switch {
	case x == nil:
		return "∅"
	case x.typ == nil:
		return "𝓤"
	case x.tilde:
		return "~" + x.typ.String()
	default:
		return x.typ.String()
	}
}

// equal报告x和y是否代表同一类型集。简单病例∅ ⊂ x、 y⊂ 𝓤 
func (x *term) equal(y *term) bool {
	switch {
	case x == nil || y == nil:
		return x == y
	case x.typ == nil || y.typ == nil:
		return x.typ == y.typ
	}

	return x.tilde == y.tilde && Identical(x.typ, y.typ)
}

// union返回union x∪ y:零、一或两个非零项。
func (x *term) union(y *term) (_, _ *term) {
	// 简单病例
	switch {
	case x == nil && y == nil:
		return nil, nil // ∅ ∪ ∅ == ∅ 
	case x == nil:
		return y, nil // ∅ ∪ y==y 
	case y == nil:
		return x, nil // x∪ ∅ == x 
	case x.typ == nil:
		return x, nil // 𝓤 ∪ y==𝓤 
	case y.typ == nil:
		return y, nil // x∪ 𝓤 == 𝓤 
	}
	// ∅ ⊂ x、 y⊂ 𝓤 

	if x.disjoint(y) {
		return x, y // x∪ y==（x，y）如果x∩ y==∅ 
	}
	// x.typ==y.typ 

	// ~t∪ ~t==~t 
	// /~t∪  T==T 
	// T∪ ~t==~t 
	// t∪  T==T 
	if x.tilde || !y.tilde {
		return x, nil
	}
	return y, nil
}

// intersect返回交叉点x∩ y、 
func (x *term) intersect(y *term) *term {
	// 简单病例
	switch {
	case x == nil || y == nil:
		return nil // ∅ ∩ y==∅ 和∩ ∅ == ∅ 
	case x.typ == nil:
		return y // 𝓤 ∩ y==y 
	case y.typ == nil:
		return x // x∩ 𝓤 == x 
	}
	// ∅ ⊂ x、 y⊂ 𝓤 

	if x.disjoint(y) {
		return nil // x∩ y==∅ 如果x∩ y==∅ 
	}
	// x.typ==y.typ 

	// ~t∩ ~t==~t 
	// /~t∩  T==T 
	// T∩ ~t==t 
	// t∩  T==T 
	if !x.tilde || y.tilde {
		return x
	}
	return y
}

// 包括报告T∈ x、 
func (x *term) includes(t Type) bool {
	// 简单病例
	switch {
	case x == nil:
		return false // t∈ ∅ == 假
	case x.typ == nil:
		return true // t∈ 𝓤 == 真正的
	}
	// ∅ ⊂ 十、⊂ 𝓤 

	u := t
	if x.tilde {
		u = under(u)
	}
	return Identical(x.typ, u)
}

// 子组件报告x⊆ y、 
func (x *term) subsetOf(y *term) bool {
	// 简单病例
	switch {
	case x == nil:
		return true // ∅ ⊆ y==真
	case y == nil:
		return false // x⊆ ∅ == 自x以来为假！=∅ 
	case y.typ == nil:
		return true // x⊆ 𝓤 == 真正的
	case x.typ == nil:
		return false // 𝓤 ⊆ y==自y以来为假！=𝓤 
	}
	// ∅ ⊂ x、 y⊂ 𝓤 

	if x.disjoint(y) {
		return false // x⊆ y==如果x为假∩ y==∅ 
	}
	// x.typ==y.typ 

	// ~t⊆ ~t==真实
	// /~t⊆ T==false 
	// T⊆ ~t==true 
	// t⊆  T==true 
	return !x.tilde || y.tilde
}

// 不相交的报告是否为x∩ y==∅. 
// x.typ和y.typ不能为零。
func (x *term) disjoint(y *term) bool {
	if debug && (x.typ == nil || y.typ == nil) {
		panic("invalid argument(s)")
	}
	ux := x.typ
	if y.tilde {
		ux = under(ux)
	}
	uy := y.typ
	if x.tilde {
		uy = under(uy)
	}
	return !Identical(ux, uy)
}
